#include "PlaceCommand.h"
#include "../view/UMLCanvas.h"

#include <algorithm>
#include <stdexcept>
#include <QDebug>

using std::runtime_error;

// FIXME: this shouldn't be here
bool Command::useful() const
{
	return true;
}

PlaceCommand::PlaceCommand(UMLDiagram& d, UMLCanvas& canvas, const UMLObject& o)
:	_diagram(d),
	_canvas(canvas),
	_prototype(o.clone()),
	_created(NULL),
	_executed(false)
{
}

PlaceCommand::PlaceCommand(const PlaceCommand& pc)
:	_diagram(pc._diagram),
	_canvas(pc._canvas),
	_prototype(pc._prototype->clone()),
	_created(pc._created),
	_executed(pc._executed)
{
	/* Unfortunately we do perform heap allocation in UMLObject::clone(), but
	 * this should be an uncommon operation. */
}

UMLObject& PlaceCommand::prototype()
{
	return *_prototype;
}

void PlaceCommand::execute()
{
	if (!_executed)
	{
		// If we have ever executed before, _created will point to the clone
		// placed onto the diagram. If so, re-add the clone so that future
		// commands that point the clone clone can also be redone.
		_created = &_diagram.add(
				(_created) ? *_created : *_prototype);

		qDebug() << "Created Object at logical "
			<< _created->rect();

		_canvas.selection().clear();
		_canvas.selection().toggle(_created);
	}
	else
	{
		/* If we've already executed, just update what we created with any
		 * modifications made to the prototype.
		 *
		 * Note: this satisfies the requirement that both operands are the same
		 * type because we made _created from _prototype.
		 */
		*_created = *_prototype;
	}

	_executed = true;
}

void PlaceCommand::unexecute()
{
	if (!_executed)
		return;

	UMLDiagram::iterator iter =
		find(_diagram.begin(), _diagram.end(), _created);

	if (iter == _diagram.end())
		throw runtime_error("PlaceCommand appears already unexecuted.");

	_diagram.remove(iter);

	_executed = false;
}

const char* PlaceCommand::name() const
{
	return "PlaceCommand";
}

